import random
import math
import ast  # 用于安全地将字符串解析为Python表达式

# 字母表映射，a=00, b=01, ..., z=25
#alphabet = {chr(i + 97): str(i).zfill(2) for i in range(26)}
class RSACipher:
    def __init__(self):
        self.p = None
        self.q = None
        self.n = None
        self.phi = None
        self.e = None
        self.d = None
        self.alphabet = {chr(i + 97): str(i).zfill(2) for i in range(26)}
    # 计算 p^q mod n
    def pow_mod(self,p, q, n):
        temp = bin(q)[2:]
        length = len(temp)
        s = 1
        for i in range(length):
            s = (s * s) % n
            high = int(temp[i])
            if high == 1:
                s = (s * p) % n
        return s

    # Miller-Rabin 素性测试
    def miller_rabin(self,n, k=5):
        if n == 2 or n == 3:
            return True
        if n % 2 == 0 or n == 1:
            return False
        r, s = 0, n - 1
        while s % 2 == 0:
            r += 1
            s //= 2
        for _ in range(k):
            a = random.randint(2, n - 2)
            x = self.pow_mod(a, s, n)
            if x == 1 or x == n - 1:
                continue
            for _ in range(r - 1):
                x = self.pow_mod(x, 2, n)
                if x == n - 1:
                    break
            else:
                return False
        return True

    # 生成公钥 e
    def generate_publickey(self,phi):
        '''while True:
            e = random.randint(2, 65535)
            if math.gcd(e, phi) == 1:
                return e'''
        e=10001
        return e

    # 扩展欧几里得算法   求私钥d
    def get_reverse(self,e, phi):
        if e > phi:
            return self.get_reverse(phi, e)
        (x1, x2, x3) = (0, 1, phi)
        (y1, y2, y3) = (1, 0, e)
        while y3 != 1:
            q = x3 // y3
            (t1, t2, t3) = (x1 - q * y1, x2 - q * y2, x3 - q * y3)
            (x1, x2, x3) = (y1, y2, y3)
            (y1, y2, y3) = (t1, t2, t3)
        return y1

    # 将字符串转换为数字 (每对两个字母转换为四位数)
    def str_to_num(self,s):
        num_str = ""
        for char in s:
            num_str += f"{ord(char):03}"  # 将字符的 ASCII 值转为三位数
        return int(num_str)


    # 将数字转换为字符串
    def num_to_str(self,num):
        num_str = str(num).zfill((len(str(num)) + 2) // 3 * 3)  # 补齐为3的倍数长度
        result = ""
        for i in range(0, len(num_str), 3):
            num_part = num_str[i:i+3]
            result += chr(int(num_part))  # 将三位数转换为字符
        return result



    # RSA 加密
    def Encrypt_RSA(self,m, e, n):
        encrypted = self.pow_mod(m, e, n)
        print("加密后得：{}".format(encrypted))
        return encrypted

    # RSA 解密
    def Decrypt_RSA(self,c, d, n):
        decrypted = self.pow_mod(c, d, n)
        print("解密后得：{}".format(decrypted))
        return decrypted

    # 分块加密
    def chunked_encrypt(self,message, e, n, chunk_size):
        encrypted_chunks = []
        for i in range(0, len(message), chunk_size):
            chunk = message[i:i+chunk_size]
            m = self.str_to_num(chunk)
            encrypted_chunks.append(self.Encrypt_RSA(m, e, n))
        return encrypted_chunks

    # 分块解密
    def chunked_decrypt(self,encrypted_chunks, d, n):
        decrypted_message = ""
        for chunk in encrypted_chunks:
            decrypted_chunk = self.Decrypt_RSA(chunk, d, n)
            decrypted_message += self.num_to_str(decrypted_chunk)
        return decrypted_message.strip()

    # 从文件读取解密内容
    def read_to_decrypt(self, filename):
        values = {}
        current_key = None
        current_value = []

        with open(filename, 'r') as file:
            for line in file:
                line = line.strip()
                # 跳过空行
                if not line:
                    continue

                # 如果该行包含 `=`，表示是一个新的键值对
                if '=' in line:
                    if current_key is not None:
                        # 保存之前的值
                        values[current_key] = (
                            int("".join(current_value)) if current_key not in ["encrypted_chunks", "m"]
                            else "".join(current_value) if current_key == "m"
                            else ast.literal_eval("".join(current_value))
                        )

                    # 处理新键值对
                    current_key, value_part = line.split('=', 1)
                    current_value = [value_part]
                else:
                    # 如果没有 `=`，继续拼接到当前值
                    current_value.append(line)

            # 保存最后一个键值对
            if current_key is not None:
                values[current_key] = (
                    int("".join(current_value)) if current_key not in ["encrypted_chunks", "m"]
                    else "".join(current_value) if current_key == "m"
                    else ast.literal_eval("".join(current_value))
                )

        return values

    '''def read_to_decrypt(self,filename):
        values = {}
        with open(filename, 'r') as file:
            for line in file:
                key, value = line.strip().split('=')
                if key == 'encrypted_chunks':
                    values[key] = ast.literal_eval(value)  # 解析加密块为列表
                else:
                    try:
                        values[key] = int(value)  # 安全转换为整数
                    except ValueError:
                        print(f"Warning: 解析失败，跳过值 '{value}'")
        return values'''

    # 保存到文件
    def save_to_file(self,filename="rsa.txt", **kwargs):
        with open(filename, 'a') as file:
            for key, value in kwargs.items():
                if isinstance(value, list):  # 如果是列表，转成字符串存储
                    file.write(f"{key}={value}\n")
                else:
                    file.write(f"{key}={value}\n")
            print(f"内容已保存到 {filename}")

'''# 主函数
if __name__ == '__main__':
    try:
        temp = int(input("输入1进行加密, 2进行解密："))
        if temp == 1:
            rsa_values = read_to_decrypt("rsa.txt")
            p, q = (rsa_values.get(key) for key in ('p', 'q'))
            n = p * q
            phi = (p - 1) * (q - 1)
            e = generate_publickey(phi)
            d = get_reverse(e, phi)
            d=d+phi
            print(f"公钥: (e={e}, n={n})")
            print(f"私钥: (d={d}, n={n})")
            save_to_file("rsa.txt", n=n, phi=phi, e=e, d=d)

            # 输入英文字符对或数字
            m_input = input("输入明文信息（字母或数字）：")
            if m_input.isdigit():
                m = int(m_input)  # 如果输入的是数字，保持功能不变
                c = Encrypt_RSA(m, e, n)
                save_to_file("rsa.txt", m=m,c=c)
            else:
                # 明文块大小应小于 n 的长度（比如每个块最多50字符）
                encrypted_chunks = chunked_encrypt(m_input, e, n, 50)
                print(f"加密后的块: {encrypted_chunks}")
                save_to_file("rsa.txt", encrypted_chunks=encrypted_chunks)

        elif temp == 2:
            rsa_value = read_to_decrypt("rsa.txt")
            d, n = (rsa_value.get(key) for key in ('d', 'n'))
            print("d=",d,"n=",n)
            c=rsa_value.get('c')
            if not c:
                encrypted_chunks = rsa_value.get('encrypted_chunks')  # 从文件读取加密块
                print("这里读完了chunks")
                print(encrypted_chunks)
                decrypted_message = chunked_decrypt(encrypted_chunks, d, n)
                print("这里对chunks完成了解密")
                print(f"解密后的明文字符: {decrypted_message}")
            else:
                decrypted = Decrypt_RSA(c, d, n)
                print(f"解密后的明文: {decrypted}")


    except ValueError as ve:
        print("错误：", ve)
    except Exception as e:
        print("发生了一个错误：", e)
'''